defmodule Servy.HttpServer do
  # def server do
  #   {:ok, lsock} = :gen_tcp.listen(5678, [:binary,
  #                                         packet: 0,
  #                                         active: false])
  #   {:ok, sock} = :gen_tcp.accept(lsock)
  #   {:ok, bin} = :gen_tcp.recv(sock, 0)
  #   # send response
  #   :ok = :gen_tcp.close(sock)
  #   bin
  # end

  @doc """
  Starts the server on the given `port` of localhost
  """
  def start(port) when is_integer(port) and port > 1023 do
    # Create a socket to listen for client connections
    # `listen_socket` is bound to the listening socket.
    {:ok, listen_socket} =
      :gen_tcp.listen(port, [:binary,
                             packet: :raw,
                             active: false,
                             reuseaddr: true])
    IO.puts "\n Listening for connection requests on port #{port} ...\n"

    accept_loop(listen_socket)
  end

  @doc """
  Accepts client connections on the `listen_socket`
  """
  def accept_loop(listen_socket) do
    IO.puts "Waitting to accept a client connection ...\n"

    {:ok, client_socket} = :gen_tcp.accept(listen_socket)

    IO.puts "Connection accepted!\n"

    spawn(fn -> serve(client_socket) end)

    accept_loop(listen_socket)
  end

  @doc """
  Receives the request on the `client_socket` and
  sends a response back over the same socket
  """
  def serve(client_socket) do
    IO.puts "#{inspect self()}: Working on it"
    client_socket
    |> read_request
    |> Servy.Handler.handle
    |> write_response(client_socket)
  end


  @doc """
  Receives a request on the `client_socket`
  """
  def read_request(client_socket) do
    {:ok, request} = :gen_tcp.recv(client_socket, 0)
    IO.puts " Received request:\n"
    IO.puts request
    request
  end

  @doc """
  Return a generic HTTP response
  """
  def generate_response(_request) do
    """
    HTTP/1.1 200 OK
    Content-Type: text/plain
    Contetn-Length: 6

    Hello!
    """
  end

  @doc """
  Sends the `response` over the `client_socket`
  """
  def write_response(response, client_socket) do
    :ok = :gen_tcp.send(client_socket, response)

    IO.puts " Sent response:\n"
    IO.puts response

    :gen_tcp.close(client_socket)
  end
end
